using System;
using System.Reflection;
using Rhino.Mocks;

namespace wMobinium.core.test
{
    [NUnit.Framework.TestFixture]
    public class TestMethodInfoTest
    {
        private MockRepository mocks;
        private MethodInfo methodInfoMock;

        [NUnit.Framework.SetUp]
        public void SetUp()
        {
            mocks = new MockRepository();
            methodInfoMock = mocks.CreateMock<MethodInfo>();
        }

        [NUnit.Framework.Test]
        public void EnsureThatInvokeMethodIsExecuted()
        {
            Expect.Call(methodInfoMock.Invoke(null, null)).IgnoreArguments().Return(null);
            mocks.ReplayAll();

            StubTestMethodInfo.Invoke(null);

            mocks.VerifyAll();
        }

        [NUnit.Framework.Test]
        public void EnsureThatMethodNameIsReturned()
        {
            string expectedMethodName = "AnyName";
            Expect.Call(methodInfoMock.Name).IgnoreArguments().Return(expectedMethodName);
            mocks.ReplayAll();

            NUnit.Framework.Assert.AreEqual(expectedMethodName, StubTestMethodInfo.Name);
            mocks.VerifyAll();
        }

        [NUnit.Framework.Test]
        public void EnsureThatAttributesReturnTrueWhenSetTrue()
        {
            string expectedExceptionMessage = "my exception";

            StubAttribute(typeof (CleanUpAttribute));
            StubAttribute(typeof (IgnoreAttribute));
            StubAttribute(typeof (SetUpAttribute));
            StubAttribute(typeof (TestAttribute));
            StubAttribute(typeof (TestFixtureAttribute));
            StubAttribute(typeof (TestFixtureCleanupAttribute));
            StubAttribute(typeof (TestFixtureSetUpAttribute));

            ExpectedExceptionAttribute expectedExceptionAttribute =
                new ExpectedExceptionAttribute(typeof (Exception), expectedExceptionMessage);
            StubAttribute(typeof (ExpectedExceptionAttribute));
            StubExpectedExceptionAttribute(typeof (ExpectedExceptionAttribute), expectedExceptionAttribute);

            mocks.ReplayAll();

            NUnit.Framework.Assert.IsTrue(StubTestMethodInfo.IsCleanUp);
            NUnit.Framework.Assert.IsTrue(StubTestMethodInfo.IsIgnored);
            NUnit.Framework.Assert.IsTrue(StubTestMethodInfo.IsSetUp);
            NUnit.Framework.Assert.IsTrue(StubTestMethodInfo.IsTest);
            NUnit.Framework.Assert.IsTrue(StubTestMethodInfo.IsTestFixtureCleanUp);
            NUnit.Framework.Assert.IsTrue(StubTestMethodInfo.IsTestFixtureSetUp);

            NUnit.Framework.Assert.IsTrue(StubTestMethodInfo.ExpectsException());
            NUnit.Framework.Assert.AreEqual(expectedExceptionAttribute.ExceptionType,
                                            StubTestMethodInfo.ExpectedException);
            NUnit.Framework.Assert.AreEqual(expectedExceptionMessage, StubTestMethodInfo.ExpectedExceptionMessage);
        }

        [NUnit.Framework.Test]
        public void EnsureThatAttributesReturnFalseWhenSetFalse()
        {
            StubNoAttribute();
            mocks.ReplayAll();

            NUnit.Framework.Assert.IsFalse(StubTestMethodInfo.IsCleanUp);
            NUnit.Framework.Assert.IsFalse(StubTestMethodInfo.IsIgnored);
            NUnit.Framework.Assert.IsFalse(StubTestMethodInfo.IsSetUp);
            NUnit.Framework.Assert.IsFalse(StubTestMethodInfo.IsTest);
            NUnit.Framework.Assert.IsFalse(StubTestMethodInfo.IsTestFixtureCleanUp);
            NUnit.Framework.Assert.IsFalse(StubTestMethodInfo.IsTestFixtureSetUp);

            NUnit.Framework.Assert.IsFalse(StubTestMethodInfo.ExpectsException());
            NUnit.Framework.Assert.IsNull(StubTestMethodInfo.ExpectedException);
            NUnit.Framework.Assert.IsEmpty(StubTestMethodInfo.ExpectedExceptionMessage);
        }

        public TestMethodInfo StubTestMethodInfo
        {
            get { return new TestMethodInfo(methodInfoMock); }
        }

        private void StubAttribute(Type attributeType)
        {
            Expect.Call(methodInfoMock.IsDefined(attributeType, true)).Return(true);
        }

        private void StubExpectedExceptionAttribute(Type attributeType, ExpectedExceptionAttribute expectedException)
        {
            Expect.Call(methodInfoMock.GetCustomAttributes(attributeType, true)).Repeat.Any().Return(
                new object[] {expectedException});
        }

        private void StubNoAttribute()
        {
            Expect.Call(methodInfoMock.IsDefined(null, true)).IgnoreArguments().Repeat.Any().Return(false);
            Expect.Call(methodInfoMock.GetCustomAttributes(null, true)).IgnoreArguments().Repeat.Any().Return(
                new object[] {});
        }
    }
}